# 导入标准库模块
import shutil  # 提供高级文件操作功能，如复制、移动、删除等
from pathlib import Path  # 面向对象的文件系统路径操作，比os.path更现代易用
import hashlib  # 安全哈希和消息摘要算法实现，用于文件内容校验
import subprocess
import os  # 提供操作系统相关功能，如文件系统访问
# 全局变量：当前工作目录，初始化为当前目录的Path对象
# Path对象比字符串路径更强大，可以直接进行路径拼接和属性访问
current_dir = Path('.')  # 表示当前工作目录的Path对象


def list_directory(args):
    try:
        target_dir = current_dir  # 默认使用当前目录
        if args:  # 如果提供了参数
            target_dir = current_dir / args[0]  # 拼接当前目录和参数目录
        for item in target_dir.iterdir():
            if item.is_file():
                print(f"文件: {item}")
            elif item.is_dir():
                print(f"目录: {item}")
    except Exception as e:
        # 捕获并处理所有可能的异常，如权限错误、目录不存在等
        print(f"错误: 无法列出目录内容 - {str(e)}")
def cat_file(args):
    try:
        target_dir = current_dir
        if args:
            target_dir = current_dir / args[0]
        with open(target_dir,'r',encoding='utf-8')as file:
            content =file.read()
            print(content)
    except FileNotFoundError :
        print (f"错误:文件{target_dir.resolve()}不存在")
    except UnicodeDecodeError :
        print(f"错误:无法以utf-8读取文件")
    except IsADirectoryError :
        print(f"错误：{target_dir.resolve() }是目录")
    except PermissionError :
        print(f"错误：没有权限读取{target_dir.resolve()}文件")

def edit_file(args):


    if not args:
         print("错误: 请提供要修改的文件名")
         return


    if os.name !='nt':
        print ("非windows系统，不可执行")
        return

    file_name= current_dir / args[0]
    try:
        subprocess.run(['notepad',file_name])
    except :
        print(f"错误：无法打开{file_name}")




def make_directory(args):
    if not args:  # 参数检查
        print("错误: 请提供要创建的目录名")  # 友好的错误提示
        return  # 提前返回

    dir_name = args[0]  # 获取目录名参数
    # 构建完整路径：当前目录与新建目录名拼接
    new_dir = current_dir / dir_name  # 使用Path对象进行路径拼接

    try:
        new_dir.mkdir()
        print(f"成功创建目录: {new_dir}")
    except FileExistsError:
        print(f"错误: 目录 {new_dir} 已存在")
    except Exception as e:
        print(f'错误: 创建目录失败 - {str(e)}')  # 通用错误处理


def remove_item(args):
    if not args:  # 参数验证
        print("错误: 请提供要删除的文件或目录名")
        return

    # 构建完整路径对象
    item_path = current_dir / args[0]  # 拼接当前目录和要删除的项

    try:
        if item_path.is_file():
            item_path.unlink()
            print(f"成功删除文件: {item_path}")
        elif item_path.is_dir():
            # 使用shutil.rmtree递归删除目录及其所有内容
            shutil.rmtree(item_path)
            print(f"成功删除目录: {item_path}")
        else:
            # 路径既不是文件也不是目录
            print(f"错误: {item_path} 不存在")
    except PermissionError:
        print(f"错误: 没有权限删除 {item_path}")  # 权限错误处理
    except Exception as e:
        print(f'错误: 删除操作失败 - {str(e)}')  # 其他错误处理


def copy_item(args):
    if len(args) != 2:  # 参数数量检查
        print("错误: 需要两个参数 - 源路径 目标路径")
        return

    # 构建源路径和目标路径的Path对象
    source = current_dir / args[0]  # 源文件/目录路径
    destination = current_dir / args[1]  # 目标路径

    try:
        if source.is_file():  # 处理文件复制
            # 使用shutil.copy2保留文件元数据(如修改时间)
            shutil.copy2(source, destination)
            print(f"成功复制文件 {source} 到 {destination}")
        elif source.is_dir():  # 处理目录复制
            # 使用shutil.copytree递归复制整个目录树
            shutil.copytree(source, destination)
            print(f"成功复制目录 {source} 到 {destination}")
        else:
            print(f"错误: 源路径 {source} 不存在")
    except shutil.SameFileError:
        print(f"错误: 源和目标相同")  # 防止自我复制
    except Exception as e:
        print(f'错误: 复制操作失败 - {str(e)}')


def move_item(args):

    if len(args) != 2:  # 参数验证
        print("错误: 需要两个参数 - 源路径 目标路径")
        return

    # 构建Path对象
    source = current_dir / args[0]  # 源路径
    destination = current_dir / args[1]  # 目标路径

    try:
        # 使用shutil.move进行移动操作，可以跨文件系统移动
        shutil.move(source, destination)
        print(f"成功移动 {source} 到 {destination}")
    except Exception as e:
        print(f'错误: 移动操作失败 - {str(e)}')


def change_directory(args):

    global current_dir  # 声明使用全局变量

    if not args:  # 参数检查
        print("错误: 请提供目标目录名")
        return

    # 构建新目录的Path对象
    if args[0]=="..":
        if current_dir.resolve()  == current_dir.resolve().parent:
            print(f"已经为根目录，没有上一级目录")
            return
        current_dir = current_dir.resolve().parent
        print(f"成功切换到目录: {current_dir.resolve() }")
        return

    new_dir = current_dir / args[0]  # 相对当前目录的路径

    if new_dir.is_dir():  # 检查目录是否存在
        current_dir = new_dir  # 更新全局当前目录
        print(f"成功切换到目录: {current_dir.resolve()}")


    else:
        print(f"错误: 目录 {new_dir} 不存在")


def calculate_file_hash(file_path: Path, buffer_size=4096) -> str:
    """
    计算文件哈希值函数
    功能：计算文件的SHA256哈希值，用于文件内容校验
    参数：
        file_path - 要计算哈希的文件路径(Path对象)
        buffer_size - 读取文件的缓冲区大小(字节)
    返回：文件的SHA256哈希值(十六进制字符串)
    """
    hasher = hashlib.sha256()  # 创建SHA256哈希对象

    # 以二进制模式打开文件，使用with语句确保文件正确关闭
    with file_path.open('rb') as f:
        while True:
            # 分块读取文件内容，避免大文件占用过多内存
            chunk = f.read(buffer_size)
            if not chunk:  # 读取结束
                break
            hasher.update(chunk)  # 更新哈希计算

    return hasher.hexdigest()  # 返回十六进制表示的哈希值


def cloud_Deduplication(args):
    """
    云去重功能函数
    功能：递归扫描目录，删除内容重复的文件(保留第一个遇到的副本)
    参数：args - 命令行参数列表，第一个参数为目标目录(可选)
    """
    try:
        # 确定目标目录：如果有参数则使用参数目录，否则使用当前目录
        target_dir = current_dir / args[0] if args else current_dir

        # 验证目标目录是否存在且确实是目录
        if not target_dir.exists() or not target_dir.is_dir():
            print(f"错误: 目录 {target_dir} 不存在或不是有效目录")
            return

        # 安全确认：防止误操作
        confirm = input(f"是否要对 {target_dir} 进行去重处理？(Y/N) ").strip().upper()
        if confirm != 'Y':
            print("操作已取消")
            return

        # 初始化变量
        hash_map = {}  # 哈希值到文件路径的映射字典
        duplicates_found = 0  # 发现的重复文件计数
        total_saved = 0  # 预计节省的空间(字节)

        # 递归遍历目标目录下的所有文件
        # glob('**/*')模式会递归匹配所有子目录中的文件
        for file_path in target_dir.glob('**/*'):
            if file_path.is_file():  # 只处理文件，忽略目录
                # 计算当前文件的哈希值
                file_hash = calculate_file_hash(file_path)

                if file_hash in hash_map:  # 发现重复文件
                    original_path = hash_map[file_hash]  # 获取第一个副本路径
                    try:
                        # 统计信息
                        original_size = file_path.stat().st_size  # 获取文件大小
                        total_saved += original_size  # 累计节省空间
                        duplicates_found += 1  # 增加重复计数

                        # 删除重复文件
                        # 这里直接调用之前定义的remove_item函数
                        remove_item([str(file_path), ])  # 转换为字符串参数
                    except Exception as e:
                        print(f"警告: 无法删除 {file_path} - {str(e)}")
                        continue  # 继续处理下一个文件
                else:
                    # 首次遇到此哈希值，记录到字典中
                    hash_map[file_hash] = file_path

        # 输出统计信息
        print(f"\n去重完成！发现 {duplicates_found} 个重复文件")
        # 将字节转换为MB显示，保留2位小数
        print(f"预计节省空间: {total_saved / 1024 / 1024:.2f} MB")

    except Exception as e:
        print(f"操作失败: {str(e)}")  # 异常处理


def print_working_directory(_):
    # 使用resolve()解析出绝对路径，并打印
    print(current_dir.resolve())


def exit_shell(_):
    print("退出 ...")
    exit(0)  # 正常退出程序

def echo(args):
    """模拟 echo 命令，输出参数内容，支持基本转义字符"""
    if not args:  # 如果没有参数，输出空行
        print()
        return

    try:
        # 处理转义字符
        processed_args = []
        for arg in args:
            # 替换常见的转义字符
            arg = arg.replace('\\n', '\n').replace('\\t', '\t')
            arg = arg.replace('\\r', '\r').replace('\\"', '"')
            arg = arg.replace("\\'", "'").replace('\\\\', '\\')
            processed_args.append(arg)

        # 将所有参数用空格连接并输出
        print(' '.join(processed_args))
    except Exception as e:
        print(f"echo错误: {e}")

# 命令字典：映射命令字符串到对应的处理函数
# 设计模式：命令模式，便于扩展新命令
COMMANDS = {
    "ls": list_directory,  # 列出目录内容
    "mkdir": make_directory,  # 创建目录
    "rm": remove_item,  # 删除文件/目录
    "cp": copy_item,  # 复制文件/目录
    "mv": move_item,  # 移动/重命名文件/目录
    "cd": change_directory,  # 切换目录
    "pwd": print_working_directory,  # 打印当前目录
    "cld": cloud_Deduplication,  # 云去重功能
    "exit": exit_shell, # 退出程序
    "echo": echo,
    "cat": cat_file,
    "edit":edit_file
}


def main(cmd_input)->bool:
    """
    主函数：命令行交互界面
    功能：提供持续的命令输入循环，直到用户退出
    """
    global current_dir  # 声明使用全局当前目录

    # 打印欢迎信息
    print("简单文件系统命令行工具。输入 'exit' 退出。")

    # 主循环：持续接受用户输入
    while True:
        try:
            # 显示提示符：当前目录+$，等待用户输入
            # 使用resolve()显示绝对路径更清晰


            # 处理空输入
            # if not cmd_input:
            #     continue  # 跳过本次循环

            # 解析输入：分割为命令和参数
            parts = cmd_input.split()  # 默认按空白字符分割
            cmd = parts[0].lower()  # 命令不区分大小写
            args = parts[1:]  # 剩余部分作为参数列表

            # 查找并执行命令
            if cmd in COMMANDS and args :  # 检查命令是否存在
                COMMANDS[cmd](args)  # 调用对应的处理函数
                return True
            else:

                print(f"未知命令: {cmd}")  # 无效命令提示
                return False

        except KeyboardInterrupt:  # 处理Ctrl+C中断
            print("\n使用 'exit' 命令退出程序")  # 友好提示
        except Exception as e:  # 捕获其他所有异常
            print(f"错误: {e}")  # 显示错误信息


# Python脚本标准入口
if __name__ == "__main__":
    main()  # 启动程序